/* TotalDcmListerPlugin.cpp -- Source file for class TotalDcmListerPlugin
*
* TotalDcmLister - A lister plugin for Total Commander for listing DICOM File content.
*
* Copyright (C) 2015 Captain Stark
*
* This software may be modified and distributed under the terms of the MIT license.
* See the COPYRIGHT file at the top-level directory of this distribution for details.
*/

#include "stdafx.h"
#include "TotalDcmListerPlugin.h"
#include "TotalDcmListerPluginSettings.h"
#include "DicomFileReader.h"
#include "FileNameTokenizer.h"

#include <string>
#include <sstream>

#pragma comment(linker, \
   "\"/manifestdependency:type='Win32' "\
   "name='Microsoft.Windows.Common-Controls' "\
   "version='6.0.0.0' "\
   "processorArchitecture='*' "\
   "publicKeyToken='6595b64144ccf1df' "\
   "language='*'\"")

#pragma comment(lib, "ComCtl32.lib")

#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN

/// <summary>
/// Initializes a new instance of the <see cref="TotalDcmListerPlugin" /> class.
/// </summary>
TotalDcmListerPlugin::TotalDcmListerPlugin()
: m_pluginView(nullptr)
{
}

/// <summary>
/// Finalizes an instance of the <see cref="TotalDcmListerPlugin"/> class.
/// </summary>
TotalDcmListerPlugin::~TotalDcmListerPlugin()
{
}

/// <summary>
/// Initializes the plugin view.
/// </summary>
/// <param name="parentWindow">The parent window.</param>
/// <returns>True when initialization has been performed without errors. False otherwise.</returns>
bool TotalDcmListerPlugin::InitializePluginView(const HWND& parentWindow)
{
   RECT clientRectangle;

   GetClientRect(parentWindow, &clientRectangle);
   int xPos = clientRectangle.left;
   int yPos = clientRectangle.top;
   int width = clientRectangle.right - clientRectangle.left;
   int height = clientRectangle.bottom - clientRectangle.top;

   if (nullptr != m_pluginView)
   {
      delete m_pluginView;
   }

   CWnd* parent = CWnd::FromHandle(parentWindow);

   m_pluginView = new TotalDcmListerPluginView(parent);

   if (nullptr == m_pluginView)
   {
      return false;
   }

   if (false == m_pluginView->Create(IDD_PLUGINVIEW, parent))
   {
      return false;
   }

   if (false == m_pluginView->SetWindowPos(NULL, xPos, yPos, width, height, SWP_NOZORDER))
   {
      return false;
   }

   m_pluginView->ShowWindow(SW_SHOW);

   return true;
}

/// <summary>
/// Gets the plugin's view handle.
/// </summary>
/// <returns>A window handle to the plugin's view.</returns>
HWND TotalDcmListerPlugin::GetPluginViewHandle()
{
   if (nullptr == m_pluginView)
   {
      return NULL;
   }

   return m_pluginView->GetSafeHwnd();
}

/// <summary>
/// Loads the content of the given DICOM file to the plugin's UI.
/// </summary>
/// <param name="fileToLoad">The file to load.</param>
/// <returns>True when initialization has been performed without errors. False otherwise.</returns>
bool TotalDcmListerPlugin::LoadDicomFileContent(const string& fileToLoad)
{
   if (nullptr == m_pluginView)
   {
      return false;
   }

   TotalDcmListerPluginSettings settings(m_settingsLocation);

   bool displayMissingAttributes = settings.DisplayMissingAttributes();
   wstring defaultValueForMissingAttributes = settings.DefaultValueForMissingAttributes();
   vector<DicomAttributeGroup> dicomDataToDisplay = settings.DicomDataToDisplay();

   DicomFileReader dicomFile(fileToLoad);

   FileNameTokenizer fileName(fileToLoad);
   wstringstream headerText;
   headerText << fileName.NameW << fileName.ExtensionW;
   headerText << L"\n(" << dicomFile.GetSopClassName() << L")";

   m_pluginView->SetHeaderText(headerText.str());
   
   int groupId = 1;
   for (DicomAttributeGroup group : dicomDataToDisplay)
   {
      m_pluginView->AddListViewGroup(groupId, group.Name);
      for (DicomAttribute attribute : group.Items)
      {
         if (dicomFile.HasAttribute(attribute.Tag))
         {
            wstring value = dicomFile.GetAttributeValue(attribute.Tag, defaultValueForMissingAttributes);
            m_pluginView->AddListViewItem(groupId, attribute.Name, value);
         }
         else if (displayMissingAttributes)
         {
            m_pluginView->AddListViewItem(groupId, attribute.Name, defaultValueForMissingAttributes);
         }
      }

      groupId++;
   }

   return true;
}

/// <summary>
/// Sets the settings location by extracting relevant path from the given ini file location.
/// </summary>
/// <param name="defaultInifile">The default inifile as provided by Total Commander.</param>
void TotalDcmListerPlugin::SetSettingsLocation(const string& defaultIniFile)
{
   char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
   errno_t err;

   err = _splitpath_s(defaultIniFile.c_str(), drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME, ext, _MAX_EXT);

   if (0 == err)
   {
      string settingsLocation = drive;
      settingsLocation += dir;

      m_settingsLocation = wstring(settingsLocation.begin(), settingsLocation.end());
   }
}